/*
 * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

package com.dc.gameserver.serverCore.service.managerService;

import com.dc.gameserver.baseConfig.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author : 石头哥哥
 * Date: 13-10-26</br>
 * Time: 上午11:24</br>
 * Package: Server.ServerCore.Service.LicensingProcess</br>
 * 注解： 线程池管理类
 */
public class ThreadPoolManager{

    private static final Logger LOGGER= LoggerFactory.getLogger(ThreadPoolManager.class);

	protected          ScheduledThreadPoolExecutor      aiScheduledThreadPool;     //ai处理线程池配置
    protected          ScheduledThreadPoolExecutor      purgeScheduledThreadPool;   //定时周期的移除被取消的任务
    protected          ScheduledThreadPoolExecutor       roundIntervalTimerScheduled;        //回合间隔时间
    protected          ScheduledThreadPoolExecutor       roundTimeOutTimerScheduled;      //出牌超时定时器
    protected          BlockingQueue<Runnable>           runnableBlockingQueue;//回合计时器任务列表
    protected          ScheduledThreadPoolExecutor       buffTimerScheduled;    //buf 任务执行定时器

    /*********
     * 数据分发线程和数据核心线程池（包含数据db操作部分）分开
     */
    protected          ExecutorService                   calculateCoreThread;  // 游戏核心逻辑计算使用多线程



	private ThreadPoolManager(){
        roundTimeOutTimerScheduled=new ScheduledThreadPoolExecutor(Config.DEFAULT_VALUE.SERVER_VALUE.RoundTimeOutTimerNum,new PriorityThreadFactory("#+回合出牌计时线程#",Thread.NORM_PRIORITY));
        roundIntervalTimerScheduled = new ScheduledThreadPoolExecutor(Config.DEFAULT_VALUE.SERVER_VALUE.RoundIntervalTimerNum, new PriorityThreadFactory("#+回合间隔计时线程#", Thread.NORM_PRIORITY));
        buffTimerScheduled=new ScheduledThreadPoolExecutor(Config.DEFAULT_VALUE.SERVER_VALUE.buffTimerNum, new PriorityThreadFactory("@+buf冷却处理线程+@", Thread.NORM_PRIORITY));
        if (Config.DEFAULT_VALUE.SERVER_VALUE.useMultleThread)calculateCoreThread= Executors.newFixedThreadPool(Config.DEFAULT_VALUE.SERVER_VALUE.calculateThreads, new PriorityThreadFactory("@+游戏核心逻辑计算线程@+#+", Thread.NORM_PRIORITY));
        purgeScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.DEFAULT_VALUE.SERVER_VALUE.purgeTaskNum, new PriorityThreadFactory("@+销毁被取消计时任务线程池+@", Thread.NORM_PRIORITY));
        aiScheduledThreadPool=new ScheduledThreadPoolExecutor(Config.DEFAULT_VALUE.SERVER_VALUE.AIthreadNum,new PriorityThreadFactory("@+AiThreadPools+@",Thread.NORM_PRIORITY));
		// 周期执行清理任务 Initial 10 minutes, delay 5 minutes.
        schedulePurgeTaskAtFixedRate(new PurgeTask(), 600000L, 300000L);
        runnableBlockingQueue=roundTimeOutTimerScheduled.getQueue();
	}


    /** temp workaround for VM issue */
    private static final long MAX_DELAY = Long.MAX_VALUE / 1000000 / 2;

    /**
     * 单例对象
     * @return
     */
    public static ThreadPoolManager getInstance(){
        return SingletonHolder._instance;
    }


    /**
     * 核心逻辑计算
     * @param runnable
     */
    public void   executeCalculate(final Runnable runnable){
        calculateCoreThread.execute(runnable);
    }

    /**
     * 回合间隔 定时
     * 延迟 delay毫秒计时
     * @param r
     * @param delay  2000 毫秒
     * @return
     */
    public ScheduledFuture<?> scheduleRoudIntervalTime(Runnable r,long delay){
        delay = ThreadPoolManager.validateDelay(delay);
        return roundIntervalTimerScheduled.schedule(r,delay,TimeUnit.MILLISECONDS);
    }
    /**
     * 执行 超时回合
     * @param r
     * @param delay 30秒
     * @return
     */
    public ScheduledFuture<?> scheduleRoudTimeOut(Runnable r,long delay){
        delay = ThreadPoolManager.validateDelay(delay);
        return roundTimeOutTimerScheduled.schedule(r,delay,TimeUnit.MILLISECONDS);
    }


    /**
     * 在回合开始之后，就会移除注册的回合计时任务
     * 移除指定的计时任务
     */
    public void removeRoudTimeOutTimerTask(RunnableScheduledFuture<?> task){
        //如果 计时队列中存在task
        if (runnableBlockingQueue.contains(task)){
            runnableBlockingQueue.remove(task);
            LOGGER.debug("移除计时队列中的task:"+ task);
        }
    }
    /**
     * 周期 执行 超时回合
     * @param r
     * @param initial
     * @param delay
     * @return
     */
    public ScheduledFuture<?> scheduleRoudTimeOutAtFixedRate(Runnable r, long initial, long delay){
        delay = ThreadPoolManager.validateDelay(delay);
        initial = ThreadPoolManager.validateDelay(initial);
        return   roundTimeOutTimerScheduled.scheduleAtFixedRate(r,initial,delay,TimeUnit.MILLISECONDS);
    }


    /**
     *  buf 冷却
     * @param r
     * @param delay 冷却时间
     * @return
     */
	public ScheduledFuture<?> scheduleBuf(Runnable r, long delay){
		try{
			delay = ThreadPoolManager.validateDelay(delay);
			return buffTimerScheduled.schedule(r, delay, TimeUnit.MILLISECONDS);
		}catch (RejectedExecutionException e){
			return null;
		}
	}

    /**
     *  周期buf 冷却
     * @param r
     * @param initialdelay   首次  延迟执行时间
     * @param period  执行间隔周期
     * @return
     */
	public ScheduledFuture<?> scheduleBufAtFixedRate(Runnable r, long initialdelay, long period){
		try{
            period = ThreadPoolManager.validateDelay(period);
            initialdelay = ThreadPoolManager.validateDelay(initialdelay);
			return buffTimerScheduled.scheduleAtFixedRate(r, initialdelay, period, TimeUnit.MILLISECONDS);
		}catch (RejectedExecutionException e){
			return null; /* shutdown, ignore */
		}
	}


    /**
     *  delay 执行 ai
     * @param r
     * @param delay
     * @return
     */
	public ScheduledFuture<?> scheduleAi(Runnable r, long delay){
		try{
			delay = ThreadPoolManager.validateDelay(delay);
			return aiScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
		}catch (RejectedExecutionException e){
			return null; /* shutdown, ignore */
		}
	}

    /**
     *  执行ai
     * @param r
     */
    public void executeAi(Runnable r){
        aiScheduledThreadPool.execute(r);
    }



    /**
     * 周期执行ai
     * @param  r
     * @param delay
     * @param period
     * @return
     */
	public ScheduledFuture<?> scheduleAiAtFixedRate(Runnable r, long delay, long period){
		try{
            period = ThreadPoolManager.validateDelay(period);
            delay = ThreadPoolManager.validateDelay(delay);
			return aiScheduledThreadPool.scheduleAtFixedRate(r, delay, period, TimeUnit.MILLISECONDS);
		}
		catch (RejectedExecutionException e)
		{
			return null; /* shutdown, ignore */
		}
	}

    /**
     *
     * @param r
     * @param period
     * @param delay
     * @return
     */
    private ScheduledFuture<?> schedulePurgeTaskAtFixedRate(Runnable r, long delay, long period){
        try{
            delay = ThreadPoolManager.validateDelay(delay);
            period = ThreadPoolManager.validateDelay(period);
            return purgeScheduledThreadPool.scheduleAtFixedRate(r, delay, period, TimeUnit.MILLISECONDS);
        }
        catch (RejectedExecutionException e)
        {
            return null; /* shutdown, ignore */
        }
    }


    /**
     * 延迟时间验证
     * @param delay
     * @return
     */
    private static long validateDelay(long delay){
        if (delay < 0) {
            delay = 0;
        }
        else if (delay > MAX_DELAY)
        {
            delay = MAX_DELAY;
        }
        return delay;
    }


    /**
     * 线程池工厂
     */
    private static class PriorityThreadFactory implements ThreadFactory{
		private final int _prio;
		private final String _name;
		private final AtomicInteger _threadNumber = new AtomicInteger(1);
		private final ThreadGroup _group;
		
		public PriorityThreadFactory(String name, int prio){
			_prio = prio;
			_name = name;
			_group = new ThreadGroup(_name);
		}
		
		@Override
		public Thread newThread(Runnable r){
			Thread t = new Thread(_group, r, _name + "-" + _threadNumber.getAndIncrement());
			t.setPriority(_prio);
			return t;
		}
		
		public ThreadGroup getGroup()
		{
			return _group;
		}
	}

    /**
     * Tries to remove from the work queue all {@link Future}
     * tasks that have been cancelled. This method can be useful as a
     * storage reclamation operation, that has no other impact on
     * functionality. Cancelled tasks are never executed, but may
     * accumulate in work queues until worker threads can actively
     * remove them. Invoking this method instead tries to remove them now.
     * However, this method may fail to remove tasks in
     * the presence of interference by other threads.
     */
	protected class PurgeTask implements Runnable{
		@Override
		public void run(){
             roundIntervalTimerScheduled.purge();
             roundTimeOutTimerScheduled.purge();
             buffTimerScheduled.purge();
            aiScheduledThreadPool.purge();
		}
	}

    //单例
	private static class SingletonHolder{
		private static final ThreadPoolManager _instance = new ThreadPoolManager();
	}
}